Skip to main content

compio_driver\sys\pal\windows/
mod.rs

1use std::{fmt, io, ptr, task::Poll};
2
3pub use windows_sys::Win32::Networking::WinSock::CMSGHDR as CmsgHeader;
4use windows_sys::{
5    Win32::{
6        Foundation::{
7            ERROR_BROKEN_PIPE, ERROR_HANDLE_EOF, ERROR_IO_INCOMPLETE, ERROR_IO_PENDING,
8            ERROR_NETNAME_DELETED, ERROR_NO_DATA, ERROR_NOT_FOUND, ERROR_PIPE_CONNECTED,
9            ERROR_PIPE_NOT_CONNECTED, GetLastError,
10        },
11        Networking::WinSock::{SIO_GET_EXTENSION_FUNCTION_POINTER, WSAIoctl},
12        System::IO::{CancelIoEx, OVERLAPPED},
13    },
14    core::GUID,
15};
16
17use crate::syscall;
18
19mod_use::mod_use![fd];
20
21pub mod reexport {
22    pub use super::Overlapped;
23}
24
25/// The overlapped struct we actually used for IOCP.
26#[repr(C)]
27pub struct Overlapped {
28    /// The base [`OVERLAPPED`].
29    pub base: OVERLAPPED,
30    /// The unique ID of created driver.
31    pub driver: RawFd,
32}
33
34impl fmt::Debug for Overlapped {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        f.debug_struct("Overlapped")
37            .field("base", &"OVERLAPPED")
38            .field("driver", &self.driver)
39            .finish()
40    }
41}
42
43impl Overlapped {
44    pub(crate) fn new(driver: RawFd) -> Self {
45        Self {
46            base: unsafe { std::mem::zeroed() },
47            driver,
48        }
49    }
50}
51
52// SAFETY: neither field of `OVERLAPPED` is used
53unsafe impl Send for Overlapped {}
54unsafe impl Sync for Overlapped {}
55
56#[inline]
57pub fn winapi_result(transferred: u32) -> Poll<io::Result<usize>> {
58    let error = unsafe { GetLastError() };
59    assert_ne!(error, 0);
60    match error {
61        ERROR_IO_PENDING => Poll::Pending,
62        ERROR_IO_INCOMPLETE
63        | ERROR_NETNAME_DELETED
64        | ERROR_HANDLE_EOF
65        | ERROR_BROKEN_PIPE
66        | ERROR_PIPE_CONNECTED
67        | ERROR_PIPE_NOT_CONNECTED
68        | ERROR_NO_DATA => Poll::Ready(Ok(transferred as _)),
69        _ => Poll::Ready(Err(io::Error::from_raw_os_error(error as _))),
70    }
71}
72
73#[inline]
74pub fn win32_result(res: i32, transferred: u32) -> Poll<io::Result<usize>> {
75    if res == 0 {
76        winapi_result(transferred)
77    } else {
78        Poll::Ready(Ok(transferred as _))
79    }
80}
81
82#[inline]
83pub fn winsock_result(res: i32, transferred: u32) -> Poll<io::Result<usize>> {
84    if res != 0 {
85        winapi_result(transferred)
86    } else {
87        Poll::Ready(Ok(transferred as _))
88    }
89}
90
91#[inline]
92pub fn cancel(handle: RawFd, optr: *mut OVERLAPPED) -> io::Result<()> {
93    match syscall!(BOOL, CancelIoEx(handle as _, optr)) {
94        Ok(_) => Ok(()),
95        Err(e) => {
96            if e.raw_os_error() == Some(ERROR_NOT_FOUND as _) {
97                Ok(())
98            } else {
99                Err(e)
100            }
101        }
102    }
103}
104
105pub fn get_wsa_fn<F>(handle: RawFd, fguid: GUID) -> io::Result<Option<F>> {
106    let mut fptr = None;
107    let mut returned = 0;
108    syscall!(
109        SOCKET,
110        WSAIoctl(
111            handle as _,
112            SIO_GET_EXTENSION_FUNCTION_POINTER,
113            std::ptr::addr_of!(fguid).cast(),
114            std::mem::size_of_val(&fguid) as _,
115            std::ptr::addr_of_mut!(fptr).cast(),
116            std::mem::size_of::<F>() as _,
117            &mut returned,
118            ptr::null_mut(),
119            None,
120        )
121    )?;
122    Ok(fptr)
123}